Investigating ADHD subtypes

by Béatrice De Koninck & Pénélope Pelland-Goulet
In [7]:
from IPython.display import Image 

Image("img/adhd.png")
Out[7]:

Our backgrounds

In [5]:
from IPython.display import Image 

Image("img/differences.png")
Out[5]:

ADHD

The Diagnostic and Statistical Manual of Mental Disorders, fifth edition (DSM-5) defines attention deficit–hyperactivity disorder (ADHD) as a by symptoms of impulsivity, inattention, and hyperactivity that emerge in childhood (Table 1). ADHD was initially considered to be solely a childhood disorder, and the diagnosis of adult ADHD2 was controversial.3 However, long-term follow-up studies revealed that in 40 to 60% of children with ADHD, the disorder persists into adulthood.4–7

Research question:

The ADHD subtypes are a controversial aspect of ADHD litterature; number of subtypes and their description vary accross publications.
Most subtype classification are based on behavioral/cognitive measures but lack biomarkers (Hegerl et al. 2016; Olbrich, Dinteren & Arns, 2015).
DSM-IV identifies 3 subtypes: Inattentive, Hyperactive and Mixed.

Using our EEG data in combination with behavioral and cognitive measures; can we reproduce the main (DSM) ADHD subtypes?

Description of our dataset:

- 96 college students with ADHD were recruited for this study
- Data consisted of 3 measures:
- Pre-processed eeg data (absolute power for 19 electrodes in 4 wavebands (Delta, Theta, Alpha, Beta) (10/20 system))
- 4 self-report measures from que Conners Scale:
   - Inattention/memory, 
   - Hyperactivity/resltessness, 
   - Impulsivity/emotional lability, 
   - Self-concept  
- DSM subtype classification based on the self-report measures (mainly inattentive vs mainly hyperactive vs mixed)
- 6 behavioral measures from the IVA-II test:
   - General, auditive and visual scores for attentionnal quotient 
   - General, auditive and visual scores for response control quotient 

How can we investigate ADHD subtypes?

Similarity network fusion is a method which allows the creation of similarity networks using different types of data.

snf.PNG source: Wang et al. 2014

What we learned from SNF...

Don't rush!!

Final method chosen for our project:

- PCA analysis
- k nearest-neighbour

Our analysis

THIS SLIDE AND THE NEXT ONE ARE TO BE PUSHED AT THE END OF THE PRESENTATION.

What lessons we learned from this project

Don't rush
Data preprocessing and formatting is important and takes time

What tools we learned for this project

- Jupyter Notebook, Jupyter slides
- Git & Github
- Python
- Plotly, matplotlib
- K-nn, PCA, topoplots (hytools), snfpy
- Data formatting (pandas, numpy, etc)

We've looked at our means, counts, standard deviations, now let's visualize our distributions and measure their normality

Normality is measured using the Shapiro-Wilk test. If the returned value has a p < 0,05; the null hypothesis is rejected, pointing towards a non-normal distribution. Careful with the negative exposants!

Let's start with the Connors dataset

In [15]:
# Plot distribution
sns.distplot(df_conners['cIM'], color='green', rug=True)
# Test data normality
print('Test result and p value are:',(stats.shapiro(df_conners['cIM'])))
Test result and p value are: (0.9636342525482178, 2.50556929836056e-39)
In [16]:
# Plot distribution
sns.distplot(df_conners['cHR'], color='green', rug=True)
# Test data normality
print('Test result and p value are:',(stats.shapiro(df_conners['cHR'])))
Test result and p value are: (0.9744826555252075, 3.754574644685725e-34)
In [17]:
# Plot distribution
sns.distplot(df_conners['cIE'], color='green', rug=True)
# Test data normality
print('Test result and p value are:',(stats.shapiro(df_conners['cIE'])))
Test result and p value are: (0.9720873832702637, 1.994776461682145e-35)
In [18]:
# Plot distribution
sns.distplot(df_conners['cSC'], color='green', rug=True)
# Test data normality
print('Test result and p value are:',(stats.shapiro(df_conners['cSC'])))
Test result and p value are: (0.9808207154273987, 2.9404705305593402e-30)

After organizing our dataset into manipulable data, we used a Shapiro test to determine if each of our variables was normally distributed: none of them were normally distributed.

In this case, instead of using parametric tests to describe our data, we used non-parametric tests such as Wilcoxon test (equivalent to paired t-test) and Kruskal-Wallis (equivalent to a two-ways anova).

We started with the Conners Questionnaire.

In [20]:
# Create distplot with custom bin_size
fig = ff.create_distplot(hist_data, group_labels, show_hist=False)
fig.update_layout(title_text='Conners Questionnaire : Self report data')
fig.show()

Here is the distribution for our behavioral measures (IVA-II)

In [28]:
# Create distplot with custom bin_size
fig = ff.create_distplot(hist_data, group_labels, show_hist=False)
fig.update_layout(title_text='IVA-II : Behavioral data')
fig.show()

We also looked at linear regressions and scatter plots for our behavioral data.

note that not all plots are presented, as they are not the main focus of this presentation. They all presented similar distributions and regressions.
In [40]:
fig = px.scatter(df, x="RCQtot", y="Aqtot", facet_col="adhdtype", color="Gender", trendline="ols")
fig.show()

In order to visualize EEG distribution, scalp plots were created using hytools

https://github.com/hyruuk/hytools/blob/master/hytools/meg_utils.py

Let's start with a general topomap of every participant's EEG data

As a starter, we looked at the general scalp distributions of the mean absolute power.

In [54]:
from mne.io import read_raw_ctf
import os
import matplotlib
import mne
import numpy as np
from mne.preprocessing import ICA, create_eog_epochs, create_ecg_epochs
import time
from IPython.display import clear_output
import mne
import matplotlib.pyplot as plt
from scipy.io import savemat, loadmat
from mpl_toolkits.axes_grid1 import make_axes_locatable
from bokeh.models import HoverTool
import bokeh.plotting as bplt

def array_topoplot(toplot, ch_xy, showtitle=True, titles=titles, savefig=False, figpath=None, vmin=0, vmax=30, cmap='jet', with_mask=False, masks=None, show=True):
    #create fig
    mask_params = dict(marker='o', markerfacecolor='w', markeredgecolor='k', linewidth=0, markersize=5)
    fig, ax = plt.subplots(1,len(toplot), figsize=(20,10))
   # mplcursors.cursor(hover=True)
    for i, data in enumerate(toplot):
        if with_mask == False:
            image,_ = mne.viz.plot_topomap(data=data, pos=ch_xy, cmap=cmap, vmin=vmin, vmax=vmax, axes=ax[i], show=False, contours=None, extrapolate='box', outlines='head')
        elif with_mask == True:
            image,_ = mne.viz.plot_topomap(data=data, pos=ch_xy, cmap=cmap, vmin=vmin, vmax=vmax, axes=ax[i], show=False, contours=None, mask_params=mask_params, mask=masks[i], extrapolate='box', outlines='head')
        #option for title
        if showtitle == True:
            ax[i].set_title(titles[i], fontdict={'fontsize': 20, 'fontweight': 'heavy'})
    #add a colorbar at the end of the line (weird trick from https://www.martinos.org/mne/stable/auto_tutorials/stats-sensor-space/plot_stats_spatio_temporal_cluster_sensors.html#sphx-glr-auto-tutorials-stats-sensor-space-plot-stats-spatio-temporal-cluster-sensors-py)
    divider = make_axes_locatable(ax[-1])
    ax_colorbar = divider.append_axes('right', size='5%', pad=0.05)
    plt.colorbar(image, cax=ax_colorbar)
    ax_colorbar.tick_params(labelsize=14)
    #save plot if specified
    if savefig == True:
        plt.savefig(figpath, dpi=300)
    if show == True:
        plt.show()
        plt.close(fig=fig)
    else:
        plt.close(fig=fig)
    return fig
In [55]:
array_topoplot(data, ch_xy); # ";" needed in notebook so it doesn't print in double, maybe remove if on other ide

Then, we looked at each adhd subtype's general scalp plot

This is the scalp plot for adhd subtype 1; Inattentive
In [58]:
array_topoplot(data_adhd1, ch_xy);
And this is the scalp plot for adhd subtype 2; mixed (remember that hyperactive subtype's n was of only 2 participants, so they are not included)
In [60]:
array_topoplot(data_adhd2, ch_xy);
We also plotted the difference between both adhd subtypes. As we can see, they are quite similar. Alpha waves had a little bit less amplitude for the inattentive group, especially at occipital electrodes. The two groups were statistically different.
In [62]:
array_topoplot(divide_adhd, ch_xy, vmin = -1, vmax = 1);

Now, let's investigate possible gendered differences in fft absolute power.

Let's start with women.

We also plotted the eeg scalp distribution for women.

In [65]:
array_topoplot(data_gender1, ch_xy);

And did the same for men.

In [67]:
array_topoplot(data_gender2, ch_xy);

If we want to clearly see the difference between men and women's eeg, we can compare their difference on a scalp plot!

Once again, both groups were significantly different.
In [69]:
array_topoplot(divide_gender, ch_xy, vmin=-1.5, vmax=1.5);